#include "bib_Simulacion_Disco.h"

extern CONFIG_EST config;
extern float tiempoLecturaSector;
extern long posicionCabezal;
extern HANDLE heap;
extern DB *baseDatos;
extern HANDLE mutexDisco;

int leerDesdeDisco(long dirLogica, char *datosSector);

int imprimirComportamientosDefinidos(void){

	char valor[20];

	tiempoLecturaSector = (float) MILI_SEG_EN_MIN / (config.RPM * config.sectores);
	
	sprintf(valor, "%.2f ms", (config.sectores + config.cilindros) * tiempoLecturaSector / 2); /*El tiempo de moverse de un sector a otro es el mismo que el de una pista a otra*/
	imprimirLog(INFO, "Tiempo medio de busqueda de un sector:", valor);
	
	sprintf(valor, "%.2f ms", (config.sectores + config.cilindros) * tiempoLecturaSector);
	imprimirLog(INFO, "Peor tiempo de busqueda de un sector:", valor);

	sprintf(valor, "%.2f Bytes/seg", (float) config.RPM * config.sectores * TAM_SECTOR / 60);
	imprimirLog(INFO, "Tasa de transferencia:", valor);
	
	sprintf(valor, "%d Bytes", config.sectores * config.cilindros * TAM_SECTOR);
	imprimirLog(INFO, "Capacidad total del disco:", valor);
	
	sprintf(valor, "%d Bytes", config.sectores * config.cilindros);
	imprimirLog(INFO, "Cantidad de sectores", valor);
	
	sprintf(valor, "%.2f ms", TIEMPO_LECTURA_REG_CACHE * 5);
	imprimirLog(INFO, "Tiempo medio acceso a cache:", valor);
	
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int obtenerSectores(long *dirLogica, int cantSectores, char invocador){

	char i;
	char msg[25 + 1];
	char *datosSector;
	int len;
	int aciertos = 0;
	
	if (alocarMemoria(heap, TAM_SECTOR + 1, &datosSector))
		return EXIT_FAILURE;
	*(datosSector + TAM_SECTOR) = '\0';

	sprintf(msg, "%d", posicionCabezal);
	imprimirLog(INFO, "Posicion actual:", msg);

	for (i = 0; i < cantSectores; i ++){
			
		sprintf(msg, "%d", *(dirLogica + i));
	
		if (*(dirLogica + i) < 0 || *(dirLogica + i) > (config.sectores * config.cilindros - 1)){
			imprimirLog(ERROR, "Sector fuera del rango valido", msg);
			liberarMemoria(heap, datosSector);
			return EXIT_FAILURE;
		}	
		
		leerDesdeCache(*(dirLogica + i), datosSector);	
		
		if (!strcmp(datosSector, "")){
			if (leerDesdeDisco(*(dirLogica + i), datosSector)){
				imprimirLog(ERROR, "No se pudo leer del disco el sector", msg);
				liberarMemoria(heap, datosSector);
				return EXIT_FAILURE;
			}
		}
		else
			aciertos++;
			
		if (invocador == FLAG_COMANDO)
			
			if ((len = (int) strlen(datosSector)) > 20){
				memset(msg, '\0', 25 + 1);
				strncpy(msg, datosSector, 10);
				strcat(msg, " ... ");
				strncat(msg, datosSector + len - 9, 10);
				imprimirLog(INFO, "Datos Leidos:", msg);
			}
			else
				imprimirLog(INFO, "Datos Leidos:", datosSector);
	}
	
	sprintf(msg, "%d/%d", aciertos, cantSectores - aciertos);
	imprimirLog(INFO, "Promedio hit/miss:", msg);
	
	liberarMemoria(heap, datosSector);
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int leerDesdeDisco(long dirLogica, char *datosSector){

	char *msg;
	int dirCilindro, dirSector;
	int cilindroActual, sectorActual;
	int sentido;
	long cantMovimientos = 0;
	
	if (alocarMemoria(heap, (DIGITOS_MAX_DIR_LOGICA + 2) * (config.sectores + config.cilindros) + 1, &msg))
		return EXIT_FAILURE;
	
	strcpy(msg, "");

	deLogicaAFisica(dirLogica, &dirCilindro, &dirSector);
	deLogicaAFisica(posicionCabezal, &cilindroActual, &sectorActual);
	
	if (dirCilindro < cilindroActual)
		sentido = (-1);
	else
		sentido = 1;
	
	while (dirCilindro != cilindroActual){
		cilindroActual += sentido;
		sectorActual = (sectorActual + 1) % config.sectores;
		cantMovimientos++;
		deFisicaALogica(&posicionCabezal, cilindroActual, sectorActual);
		sprintf(msg, "%s, %d", msg, posicionCabezal);
	}
	
	while (dirSector != sectorActual){
		sectorActual = (sectorActual + 1) % config.sectores;
		cantMovimientos++;
		deFisicaALogica(&posicionCabezal, cilindroActual, sectorActual);
		sprintf(msg, "%s, %d", msg, posicionCabezal);
	}
	
	if (!cantMovimientos){
		sprintf(msg, "%d", posicionCabezal);
		imprimirLog(INFO, "Sectores leidos", msg);
	}
	else
		imprimirLog(INFO, "Sectores leidos", msg + 2);
	sprintf(msg, "%.2f ms", cantMovimientos * tiempoLecturaSector);
	imprimirLog(INFO, "Tiempo Consumido", msg);
	
	if (leerBD(baseDatos, &dirLogica, datosSector))
		return EXIT_FAILURE;
	
	if (agregarRegCache(dirLogica, datosSector, heap))
		return EXIT_FAILURE;
		
	eliminarRegCache(heap);
	
	liberarMemoria(heap, msg);
	
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int deLogicaAFisica(long direccionLogica, int *cilindro, int *sector){

	*cilindro = direccionLogica / config.sectores;
	*sector = direccionLogica % config.sectores;
	
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int deFisicaALogica(long *direccionLogica, int cilindro, int sector){

	*direccionLogica = config.sectores * cilindro + sector;
	
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int mostrarPosicionCabezal(void){

	char poscLogica[DIGITOS_MAX_DIR_LOGICA * 3];
	char poscFisica[50];
	int cilindro, sector;
	
	sprintf(poscLogica, "Direccion logica: %d,", posicionCabezal);
	deLogicaAFisica(posicionCabezal, &cilindro, &sector);
	sprintf(poscFisica, "Cilindro: %d, Cabezal: 1, Sector: %d", cilindro, sector);
	
	imprimirLog(INFO, poscLogica, poscFisica);
	
	return EXIT_SUCCESS;
}
/*=====================================================================================*/
int crearMutexDisco(void){

	if ((mutexDisco = CreateMutex(NULL, FALSE, NULL)) == NULL){
		imprimirLog(ERROR, "No se pudo crear el mutex para el Disco:", "");
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}